package cpu;


import Escalonador.Escalonador;
import Programas.Processo;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Edilson Anselmo CorrÃªa JÃºnior
 */

public class Cpu extends Thread {    
    ArrayList<Processo> processosLocal;
    ArrayList<Processo> processosGlobal;
    Escalonador escalonador;
    

    public Cpu(Escalonador e) {
        escalonador = e;
        processosLocal = new ArrayList<Processo>();
        processosGlobal = new ArrayList<Processo>();;
       
    }

    public Cpu() {
        processosLocal = new ArrayList<Processo>();
        processosGlobal = new ArrayList<Processo>();
    }
    /**
     * Ã� medida que chegam processos ao ArrayList chamado processosGlogal
     * a Thread se encarrega de executar tais processos;
     */
    public void run() {
        while (true) {
            processosLocal.addAll(processosGlobal);
            processosGlobal.removeAll(processosLocal);
            ArrayList<Processo> proRemovidos = new ArrayList<Processo>();
            Iterator<Processo> p = processosLocal.iterator();
            while (p.hasNext()) {
                Processo processo = p.next();
                if (processo != null) {
                    try {                        
                        executaProcesso(processo);
                        proRemovidos.add(processo);
                        escalonador.retornaProcesso(processo);
                        processo.mudarEstado("executando");
                        sleep(5500);
                        escalonador.ListaProcesso.put(processo.getIdProcesso(), processo);
                        //sleep(4500);
                        executaProcesso(processo);
                        proRemovidos.add(processo);
                        escalonador.retornaProcesso(processo);
                        escalonador.ListaProcesso.put(processo.getIdProcesso(), processo);
                       // System.out.println(processo.getIdProcesso()+ " " + processo.getEstado());

                    } catch (InterruptedException ex) {
                        Logger.getLogger(Cpu.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
            processosLocal.removeAll(proRemovidos);
        }
    }
    /**
     * MÃ©todo que adiciona novos processos para serem executados 
     * na CPU. 
     * @param p: Processo que serÃ¡ adicionado a lista de execuÃ§Ãµes da CPU.
     */
    public void addProcesso(Processo p) {
        processosGlobal.add(p);
    }
    /**
     * MÃ©todo que simula a execuÃ§Ã£o de determinado processo em uma CPU.
     * @param p: Processo que serÃ¡ executado pela CPU.
     * @throws InterruptedException
     */
   // int aux;
    private void executaProcesso(Processo p) throws InterruptedException {
        if (p != null) {
            Random r = new Random();          
            p.mudarEstado(r.nextBoolean() ? "pronto" : "bloqueado");
            sleep(r.nextInt(100+p.getQuantum()));
            p.setModificado(r.nextBoolean());
            p.setReferenciado(r.nextBoolean());
            p.setCount(p.getCount()+1);
            p.referenciaAging(p.isReferenciado());
            p.setTimestemp(p.getTimestemp()+p.getQuantum());
            p.setInstUltUso(new Timestamp(System.currentTimeMillis()));
           
            
        }
    }
    
    
}
